package com.chuangjiangx.member.basic.ddd.domain.service;

import com.chuangjiangx.commons.wx.WXConstant;
import com.chuangjiangx.commons.wx.msg.WXMsgApiUtils;
import com.chuangjiangx.commons.wx.msg.model.SendResp;
import com.chuangjiangx.commons.wx.msg.model.TemplateMsg;
import com.chuangjiangx.member.basic.ddd.domain.model.msg.*;
import com.chuangjiangx.member.coupon.ddd.domain.service.MbrCardDomainService;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrAccount;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserMapping;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserMappingRepository;
import com.chuangjiangx.member.basic.ddd.domain.model.Member;
import com.chuangjiangx.member.stored.ddd.domain.model.MbrStoredStream;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserMappingType;
import com.chuangjiangx.member.basic.ddd.domain.model.MemberId;
import com.chuangjiangx.member.basic.ddd.domain.model.MerchantId;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreType;
import com.chuangjiangx.member.stored.ddd.domain.model.MbrOrderRefund;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @author cj-ch
 * @date 2018/1/31 上午11:58
 */
@Slf4j
@Service
public class MemberMsgDomainService {


    @Autowired
    private MbrUserMappingRepository mbrUserMappingRepository;
    @Autowired
    private MemberRedisDomainService memberRedisDomainService;
    @Autowired
    private MemberDomainService memberDomainService;
    @Autowired
    private MbrCardDomainService mbrCardDomainService;

    /**
     * 发送消息
     *
     * @param memberId   会员ID
     * @param merchantId 商户Id
     * @param mbrWXMsg   消息
     */
    void sendWxMsg(MemberId memberId, MerchantId merchantId, AbstractMbrWXMsg mbrWXMsg) {
        //获取mopenid(商户公众号的)
        MbrUserMapping userMapping = mbrUserMappingRepository.from(memberId, merchantId, MbrUserMappingType.WX);
        if (userMapping == null) {
            log.warn("发送微信模板消息时,获取openid失败!memberId={},merchantId={}", memberId.getId(), merchantId.getId());
            return;
        }
        //商户公众号openid
        String mopenId = userMapping.getMopenId();
        if (StringUtils.isBlank(mopenId)) {
            log.warn("不能获取到客户的mopenid,消息推送失败!memberId={},merchantId={}", memberId.getId(), merchantId.getId());
            return;
        }

        sendWxMsg(mopenId, merchantId, mbrWXMsg);

    }

    void sendWxMsg(String mopenid, MerchantId merchantId, AbstractMbrWXMsg mbrWXMsg) {

        String templateId = memberRedisDomainService.getMerchantWxTemplateId(merchantId.getId(), mbrWXMsg.getWXMsg());
        if (StringUtils.isBlank(templateId)) {
            log.warn("发送微信模板消息时,获取微信模板Id失败!merchantId={}", merchantId.getId());
            return;
        }

        String accessToken = memberRedisDomainService.getMerchantAccessToken(merchantId.getId());

        //创建 TemplateMsg
        TemplateMsg templateMsg = new TemplateMsg.Builder(
                mopenid,
                templateId,
                mbrWXMsg.toMsgData()
        ).setUrl(mbrWXMsg.url())
                .build();


        sendWxMsg(accessToken, templateMsg);
    }

    /**
     * 发送消息
     */
    void sendWxMsg(String accessToken, TemplateMsg templateMsg) {
        try {
            //即使发送失败也不要影响其他业务
            //调用微信API发送消息
            //发送失败send也不会为null
            SendResp send = WXMsgApiUtils.send(accessToken, templateMsg);
            if (Objects.equals(WXConstant.SUCCESS_CODE, send.getErrcode())) {
                //发送成功
                log.info("微信消息模板发送成功!msgid:{}", send.getMsgid());
            } else {
                //发送失败
                log.info("微信消息模板发送失败!错误信息:{}", send.getErrmsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 推送公众号消息--积分变动提醒
     *
     * @param merchantId
     * @param mbrAccount
     * @param mbrScoreStream
     */
    public void sendMbrScoreChangeMsg(Long merchantId, MbrAccount mbrAccount, MbrScoreStream mbrScoreStream, String remark) {
        MbrScoreType scoreType = mbrScoreStream.getType();
        //符号
        String symbol = "+";
        switch (scoreType) {
            case REFUND:
            case EXCHANGE:
                symbol = "-";
                break;
            case GIFT:
            case OTHER_CONSUMPTION:
            case CONSUMER:
            default:
                break;
        }
        AbstractMbrWXMsg msg = new MbrScoreChangeMsg(
                new Date(),
                symbol + mbrScoreStream.getScore(),
                remark,
                mbrAccount.getAvailableScore()
        );
        //组装积分详情链接
        msg.setUrlSupplier(
                () -> memberDomainService.getH5ScoreDetailUrl(merchantId, mbrScoreStream)
        );
        sendWxMsg(
                mbrAccount.getMemberId(),
                new MerchantId(merchantId),
                msg);
        //同步至微信会员卡
//        mbrCardDomainService.syncScoreAmountToWx(new MerchantId(merchantId),mbrAccount);
    }

    //TODO
    public void sendMbrCardRechargeMsg(Member member, MbrAccount mbrAccount, MbrStoredStream storedStream, Supplier<String> address) {
        MbrCardRechargeMsg msg = new MbrCardRechargeMsg(
                new Date(),
                address.get(),
                storedStream.getAmount(),
                mbrAccount.getAvailableBalance()
        );
        //组装储值详情链接
        msg.setUrlSupplier(
                () -> memberDomainService.getH5StoredDetailUrl(member.getOperationInfo().getMerchantId().getId(), storedStream)
        );
        sendWxMsg(
                mbrAccount.getMemberId(),
                member.getOperationInfo().getMerchantId(),
                msg);
        //同步至微信会员卡
//        mbrCardDomainService.syncScoreAmountToWx(member.getOperationInfo().getMerchantId(),mbrAccount);
    }

    //TODO
    public void sendMbrCardConsumerMsg(Member member, MbrAccount mbrAccount, MbrStoredStream storedStream, Supplier<String> address) {
        MbrCardConsumeMsg msg = new MbrCardConsumeMsg(
                new Date(),
                address.get(),
                storedStream.getAmount(),
                mbrAccount.getAvailableBalance()
        );
        //组装储值详情链接
        msg.setUrlSupplier(
                () -> memberDomainService.getH5StoredDetailUrl(member.getOperationInfo().getMerchantId().getId(), storedStream)
        );
        sendWxMsg(
                mbrAccount.getMemberId(),
                member.getOperationInfo().getMerchantId(),
                msg);
        //同步至微信会员卡
//        mbrCardDomainService.syncScoreAmountToWx(member.getOperationInfo().getMerchantId(),mbrAccount);
    }

    //TODO
    public void sendMbrCardRefundMsg(Member member, MbrAccount mbrAccount, MbrOrderRefund mbrOrderRefund, MbrStoredStream storedStream) {
        MbrCardRefundMsg msg = new MbrCardRefundMsg(
                mbrOrderRefund.getRefundAmount(),
                mbrOrderRefund.getMbrRefundNumber(),
                mbrAccount.getAvailableBalance()
        );
        //组装储值详情链接
        msg.setUrlSupplier(
                () -> memberDomainService.getH5StoredDetailUrl(member.getOperationInfo().getMerchantId().getId(), storedStream)
        );
        sendWxMsg(
                mbrAccount.getMemberId(),
                member.getOperationInfo().getMerchantId(),
                msg);
        //同步至微信会员卡
//        mbrCardDomainService.syncScoreAmountToWx(member.getOperationInfo().getMerchantId(),mbrAccount);
    }


    /**
     * 推送会员注册成功通知--模板消息
     *
     * @param member
     * @param mopenid 商户公众号openid
     */
    public void sendMbrRegistryMsg(Member member, String mopenid) {
        AbstractMbrWXMsg msg = new MbrRegistryMsg(
                member.getMobile(),
                member.getMemberCardNum(),
                new Date()
        );
        MerchantId merchantId = member.getOperationInfo().getMerchantId();
        msg.setUrlSupplier(
                () -> memberDomainService.h5EntryUrl(merchantId.getId())
        );


        if (StringUtils.isNotBlank(mopenid)) {
            sendWxMsg(
                    mopenid,
                    merchantId,
                    msg);
        } else {
            sendWxMsg(
                    member.getId(),
                    member.getOperationInfo().getMerchantId(),
                    msg
            );
        }
    }

}
